home *** CD-ROM | disk | FTP | other *** search
- (*----------------------------------------------------------------------*)
- (* Display_DWC_Contents --- Display contents of DWC file *)
- (*----------------------------------------------------------------------*)
-
- PROCEDURE Display_DWC_Contents( DWCFileName : AnyStr );
-
- (*----------------------------------------------------------------------*)
- (* *)
- (* Procedure: Display_DWC_Contents *)
- (* *)
- (* Purpose: Displays contents of a DWC file *)
- (* *)
- (* Calling sequence: *)
- (* *)
- (* Display_DWC_Contents( DWCFileName : AnyStr ); *)
- (* *)
- (* DWCFileName --- name of DWC file whose contents are to be *)
- (* listed. *)
- (* *)
- (* Calls: *)
- (* *)
- (* Aside from internal subroutines, these routines are required: *)
- (* *)
- (* Get_Unix_Date --- convert Unix date to string *)
- (* Open_File --- open a file *)
- (* Close_File --- close a file *)
- (* Entry_Matches --- Perform wildcard match *)
- (* Display_Page_Titles *)
- (* --- Display titles at top of page *)
- (* DUPL --- Duplicate a character into a string *)
- (* *)
- (*----------------------------------------------------------------------*)
-
- (*----------------------------------------------------------------------*)
- (* Map of DWC file entry header *)
- (*----------------------------------------------------------------------*)
-
- CONST
- Max_Entries = 1800 (* Maximum # of files in DWC file *);
-
- TYPE
- FNameType = ARRAY[1..13] OF CHAR;
- ID_Type = ARRAY[1..3 ] OF CHAR;
-
- (* Header for entire DWC file *)
- DWC_Header_Type = RECORD
- Size : WORD (* Size of archive structure, future expansion *);
- Ent_SZ : BYTE (* Size of directory entry, future expansion *);
- Header : FNameType (* Name of Header file to print on listings *);
- Time : LONGINT (* Time stamp of last modification to archive *);
- Entries : LONGINT (* Number of entries in archive *);
- ID_3 : ID_Type (* The string "DWC" to identify archive *);
- END;
- (* Individual file entry *)
- DWC_Entry_Type = RECORD
- Filename : FNameType (* File and extension *);
- Size : LONGINT (* Original size *);
- Time : LONGINT (* Packed date and time *);
- New_Size : LONGINT (* Compressed size *);
- FPos : LONGINT (* Position in DWC file *);
- Method : BYTE (* Compression method *);
- SZ_C : BYTE (* Size of comment *);
- SZ_D : BYTE (* Size of dir name on add *);
- CRC : WORD (* Cyclic Redundancy Check *);
- END;
- (* Entire DWC directory *)
-
- DWC_Dir_Type = ARRAY[1..Max_Entries] OF DWC_Entry_Type;
- DWC_Dir_Ptr = ^DWC_Dir_Type;
-
- (* STRUCTURED *) CONST
- DWC_ID : ID_Type = 'DWC';
-
- VAR
- DWCFile : FILE (* DWC file to be read *);
- DWC_Entry : DWC_Entry_Type (* Entry for one file in DWC lib *);
- DWC_Header : DWC_Header_Type (* Main header for DWC file *);
- DWC_Pos : LONGINT (* Current byte offset in DWC file *);
- Bytes_Read : INTEGER (* # bytes read from DWC file file *);
- Ierr : INTEGER (* Error flag *);
- Entry_To_Get : INTEGER (* Current entry being worked on *);
- Dir_In_Memory : BOOLEAN (* TRUE if entire dir fits in RAM *);
- Dir_Ptr : DWC_Dir_Ptr (* Points to RAM-resident DWC dir *);
- Dir_Size : WORD (* Size in bytes of directory *);
- Long_Name : AnyStr (* Long file name *);
-
- (*----------------------------------------------------------------------*)
- (* Get_DWC_Header --- Get initial header entry in DWC file *)
- (*----------------------------------------------------------------------*)
-
- FUNCTION Get_DWC_Header( VAR Error : INTEGER ) : BOOLEAN;
-
- (*----------------------------------------------------------------------*)
- (* *)
- (* Function: Get_DWC_Header *)
- (* *)
- (* Purpose: Gets initial DWC header *)
- (* *)
- (* Calling sequence: *)
- (* *)
- (* OK := Get_DWC_Header( VAR Error : INTEGER ) : BOOLEAN; *)
- (* *)
- (* Error --- Error flag *)
- (* OK --- TRUE if header successfully found, else FALSE *)
- (* *)
- (*----------------------------------------------------------------------*)
-
- CONST
- BufSize = 256;
-
- VAR
- I : INTEGER;
- J : INTEGER;
- Buf : ARRAY[1..BufSize] OF CHAR;
- L : LONGINT;
- ID_Found : BOOLEAN;
- ID_Ptr : ^ID_Type;
-
- BEGIN (* Get_DWC_Header *)
- (* Assume no error to start *)
- Error := 0;
- (* Assume no space to hold entire *)
- (* directory in memory. *)
- Dir_In_Memory := FALSE;
- Dir_Ptr := NIL;
- (* Try to find ID = 'DWC' near end *)
- (* of file. We will look up to 10 *)
- (* 256 byte blocks away from end *)
- (* for this info. *)
-
- L := FileSize( DWCFile );
- I := 1;
- ID_Found := FALSE;
-
- REPEAT
- (* Position to next potential block *)
-
- DWC_Pos := L - ( I * BufSize - PRED( I ) * 5 );
-
- IF ( DWC_Pos < 0 ) THEN
- DWC_Pos := 0;
-
- SEEK( DWCFile , DWC_Pos );
- (* Read in a block of information *)
- IF ( IOResult = 0 ) THEN
- BEGIN
-
- BlockRead( DWCFile, Buf, BufSize, Bytes_Read );
-
- IF ( IOResult = 0 ) THEN
- BEGIN
- (* See if we can find "DWC" here *)
-
- J := Bytes_Read - 2;
-
- WHILE ( ( J > 0 ) AND ( NOT ID_Found ) ) DO
- BEGIN
-
- ID_Ptr := @Buf[ J ];
-
- IF ( ID_Ptr^ = DWC_ID ) THEN
- ID_Found := TRUE
- ELSE
- DEC( J );
-
- END;
- (* In case we need to try next block *)
- INC( I );
-
- END
- ELSE
- Error := Format_Error;
-
- END
- ELSE
- Error := Format_Error;
-
- UNTIL ( ( I > 10 ) OR ID_Found OR ( Error <> 0 ) );
-
- (* If we didn't find DWC, quit. *)
- IF ( NOT ID_Found ) THEN
- Error := Format_Error
- ELSE
- BEGIN (* We found DWC. *)
- (* True end of DWC file (we hope). *)
-
- DWC_Pos := DWC_Pos + J + 2;
-
- SEEK( DWCFile , DWC_Pos - SIZEOF( DWC_Header ) );
-
- BlockRead( DWCFile, DWC_Header, SIZEOF( DWC_Header ), Bytes_Read );
-
- (* Check # of entries for reasonableness *)
-
- IF ( ( DWC_Header.Entries < 0 ) OR ( DWC_Header.Entries > Max_Entries ) ) THEN
- Error := Format_Error
- ELSE
- BEGIN
- (* # entries looked OK. Pick up offset *)
- (* of first directory entry. *)
-
- WITH DWC_Header DO
- BEGIN
- Dir_Size := Entries * Ent_SZ;
- DWC_Pos := DWC_Pos - ( Dir_Size + Size );
- END;
-
- SEEK( DWCFile , DWC_Pos );
-
- IF ( IOResult <> 0 ) THEN
- Error := Format_Error;
-
- (* See if we can read entire directory *)
- (* into memory. If so, do that now. *)
-
- IF ( MaxAvail > Dir_Size ) THEN
- BEGIN
-
- GETMEM( Dir_Ptr , Dir_Size );
-
- IF ( Dir_Ptr <> NIL ) THEN
- BEGIN
-
- Dir_In_Memory := TRUE;
-
- BlockRead( DWCFile, Dir_Ptr^, Dir_Size, Bytes_Read );
-
- IF ( ( IOResult <> 0 ) OR
- ( Bytes_Read < Dir_Size ) ) THEN
- Error := Format_Error;
-
- END;
-
- END;
-
- END;
-
- END;
- (* Report success/failure to calling *)
- (* routine. *)
-
- Get_DWC_Header := ( Error = 0 );
-
- END (* Get_DWC_Header *);
-
- (*----------------------------------------------------------------------*)
- (* Get_Next_DWC_Entry --- Get next header entry in DWC file *)
- (*----------------------------------------------------------------------*)
-
- FUNCTION Get_Next_DWC_Entry( VAR DWC_Entry : DWC_Entry_Type;
- Entry_No : INTEGER;
- VAR Error : INTEGER ) : BOOLEAN;
-
- (*----------------------------------------------------------------------*)
- (* *)
- (* Function: Get_Next_DWC_Entry *)
- (* *)
- (* Purpose: Gets header information for next file in DWC file *)
- (* *)
- (* Calling sequence: *)
- (* *)
- (* OK := Get_Next_DWC_Entry( VAR DWC_Entry : DWC_Entry_Type; *)
- (* Entry_No : INTEGER; *)
- (* VAR Error : INTEGER ) : BOOLEAN; *)
- (* *)
- (* DWC_Entry --- Header data for next file in DWC file *)
- (* Error --- Error flag *)
- (* Entry_No --- Entry number to get (if resident dir) *)
- (* OK --- TRUE if header successfully found, else FALSE *)
- (* *)
- (*----------------------------------------------------------------------*)
-
- BEGIN (* Get_Next_DWC_Entry *)
- (* Assume no error to start *)
- Error := 0;
- (* Read in the file header entry. *)
-
- IF Dir_In_Memory THEN
- DWC_Entry := Dir_Ptr^[ Entry_No ]
- ELSE
- BEGIN
-
- BlockRead( DWCFile, DWC_Entry, SIZEOF( DWC_Entry ), Bytes_Read );
-
- (* If wrong size read, or header marker *)
- (* byte is incorrect, report DWC file *)
- (* format error. *)
-
- IF ( ( IOResult <> 0 ) OR ( Bytes_Read < SIZEOF( DWC_Entry ) ) ) THEN
- Error := Format_Error;
-
- END;
- (* Report success/failure to calling *)
- (* routine. *)
-
- Get_Next_DWC_Entry := ( Error = 0 );
-
- END (* Get_Next_DWC_Entry *);
-
- (*----------------------------------------------------------------------*)
- (* Display_DWC_Entry --- Display DWC file file entry info *)
- (*----------------------------------------------------------------------*)
-
- PROCEDURE Display_DWC_Entry( DWC_Entry : DWC_Entry_Type );
-
- VAR
- FName : AnyStr;
- TimeDate : LONGINT;
- DTRec : DateTime;
-
- BEGIN (* Display_DWC_Entry *)
-
- WITH DWC_Entry DO
- BEGIN
- (* Pick up file name *)
-
- FName := COPY( FileName, 1, PRED( POS( #0 , FileName ) ) );
-
- (* See if this file matches the *)
- (* entry spec wildcard. Exit if *)
- (* not. *)
-
- IF Use_Entry_Spec THEN
- IF ( NOT Entry_Matches( FName ) ) THEN
- EXIT;
- (* Get date and time of creation *)
-
- Get_Unix_Style_Date( Time, DTRec.Year, DTRec.Month, DTRec.Day,
- DTRec.Hour, DTRec.Min, DTRec.Sec );
-
- PackTime( DTRec , TimeDate );
-
- Long_Name := '';
- (* Display info about this entry *)
-
- Display_One_Entry( FName, Size, TimeDate, DWCFileName,
- Current_Subdirectory, Long_Name );
-
- END;
-
- END (* Display_DWC_Entry *);
-
- (*----------------------------------------------------------------------*)
-
- BEGIN (* Display_DWC_Contents *)
-
- (* Open DWC file and initialize *)
- (* contents display. *)
-
- IF Start_Contents_Listing( ' DWC file: ',
- Current_Subdirectory + DWCFileName, DWCFile,
- DWC_Pos, Ierr ) THEN
- BEGIN
- (* Loop over entries in DWC file *)
- (* if DWC file opened OK. *)
-
- IF Get_DWC_Header( Ierr ) THEN
- BEGIN
- (* Entry to get *)
- Entry_To_Get := 1;
- (* Loop over entries *)
-
- WHILE ( ( Entry_To_Get <= DWC_Header.Entries ) AND
- ( Get_Next_DWC_Entry( DWC_Entry , Entry_To_Get , Ierr ) ) ) DO
- BEGIN
- Display_DWC_Entry( DWC_Entry );
- INC( Entry_To_Get );
- END;
-
- END
- ELSE
- BEGIN
- Display_Error( 'Failed to get DWC header' );
- Ierr := End_Of_File;
- END;
-
- (* Dispose of RAM-resident directory *)
-
- IF ( Dir_Ptr <> NIL ) THEN
- FREEMEM( Dir_Ptr , Dir_Size );
-
- (* Close DWC file *)
-
- End_Contents_Listing( DWCFile , Ierr );
-
- END;
-
- END (* Display_DWC_Contents *);
-